/**
 * @file
 * JavaScript for AJAX.
 *
 * Declares and defines constants, global variables, functions, etc. for AJAX
 * implementation.
 */

// constant(s) =================================================================
var AJAX_METHOD_GET         = "GET";  //!< The 'GET' method.
var AJAX_METHOD_POST        = "POST"; //!< The 'POST' method.
var AJAX_REQUEST_NOT_INIT   = 0;      //!< The request is not initialized.
var AJAX_REQUEST_SET_UP     = 1;      //!< The request has been set up.
var AJAX_REQUEST_SENT       = 2;      //!< The request has been sent.
var AJAX_REQUEST_IN_PROCESS = 3;      //!< The request is in process.
var AJAX_REQUEST_COMPLETED  = 4;      //!< The request is completed.
var AJAX_STATUS_OK          = 200;    //!< The request is executed successfully.
var AJAX_STATUS_NOT_FOUND   = 404;    //!< The requested file is not found.


// global variable(s) ==========================================================
var xmlhttp = null; //!< The request object.


// implementation ==============================================================
/**
 * AJAX initialization.
 *
 * The global variable 'xmlhttp' is set upon successful initialization.
 *
 * @throw
 *  - 'Error' if AJAX is not supported by the browser.
 */
function ajaxInit() {
  // create request object
  if (window.XMLHttpRequest) {
    // ie7+, firefox, chrome, opera, safari
    xmlhttp = new XMLHttpRequest();
  } else if (window.ActiveXObject) {
    // ie5, ie6
    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
  } else {
    // ajax not supported
    throw new Error("AJAX is not supported by the browser.");
  }
}

/**
 * Sends an AJAX request.
 *
 * Key-value pairs are matched according to their positions in the 'keys' and
 * 'values' arrays. E.g.
 *   keys   = { "key1", "key2", "key3", ... }
 *   values = { "val1", "val2", "val3", ... }
 *   GET request = url?key1=val1&key2=val2&key3=val3&...
 *   POST parameters = key1=val1&key2=val2&key3=val3&...
 *
 * @param ftn
 *    Function to process response from server.
 * @param method
 *    Request method ('AJAX_METHOD_GET' or 'AJAX_METHOD_POST').
 * @param url
 *    URL to request.
 * @param keys
 *    Keys (of key-value pair) to send to server.
 * @param values
 *    Values (of key-value pair) to send to server.
 *
 * @throw
 *  - 'Error' if AJAX is not supported by the browser.
 *  - 'Error' if the request method is invalid.
 */
function ajaxSend(ftn, method, url, keys, values) {
  // check ajax initialized
  if (null == xmlhttp) {
    // initialize ajax
    ajaxInit();
  }

  // format parameters
  var params = "";
  if ((null != keys) && (null != values) && (keys.length == values.length)) {
    // parameters exist
    for (var i = 0; i < keys.length; i++) {
      params += "&" + keys[i] + "=" + values[i];
    }
    // remove first '&'
    params = params.substring(1);
  }

  // send request
  if (AJAX_METHOD_GET == method) {
    // 'get' request
    if (params.length > 0) {
      url = url + "?" + params;
    }
    xmlhttp.open(method, url, true);
    xmlhttp.onreadystatechange = ftn;
    xmlhttp.send(null);
  } else if (AJAX_METHOD_POST == method) {
    // 'post' request
    xmlhttp.open(method, url, true);
    xmlhttp.onreadystatechange = ftn;
    xmlhttp.setRequestHeader(
      "Content-type", "application/x-www-form-urlencoded"
    );
    xmlhttp.setRequestHeader("Content-length", params.length);
    xmlhttp.setRequestHeader("Connection", "close");
    xmlhttp.send(params);
  } else {
    // invalid method
    throw new Error("The request method is invalid.");
  }
}
